home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / CW GUSI 1.6.4 / src / GUSINetDB.cp < prev    next >
Text File  |  1995-08-26  |  12KB  |  511 lines

  1. /*********************************************************************
  2. Project    :    GUSI                -    Grand Unified Socket Interface
  3. File        :    GUSINetDB.cp    -    Convert internet names to adresses
  4. Author    :    Matthias Neeracher
  5.  
  6.     This file was derived from the socket library by
  7.  
  8.         Charlie Reiman    <creiman@ncsa.uiuc.edu> and
  9.         Tom Milligan    <milligan@madhaus.utcs.utoronto.ca>
  10.  
  11. Language    :    MPW C++
  12.  
  13. $Log: GUSINetDB.cp,v $
  14. Revision 1.3  1994/08/10  00:07:30  neeri
  15. Sanitized for universal headers.
  16.  
  17. Revision 1.2  1994/05/01  23:43:31  neeri
  18. getservbyname() without /etc/services would fail.
  19.  
  20. Revision 1.1  1994/02/25  02:29:36  neeri
  21. Initial revision
  22.  
  23. Revision 0.5  1993/10/31  00:00:00  neeri
  24. Deferred opening of resolver
  25.  
  26. Revision 0.4  1993/07/29  00:00:00  neeri
  27. Real getservent code (adapted from Sak Wathanasin)
  28.  
  29. Revision 0.3  1993/01/19  00:00:00  neeri
  30. Can't set aliases to NULL.
  31.  
  32. Revision 0.2  1992/11/21  00:00:00  neeri
  33. Remove force_active
  34.  
  35. Revision 0.1  1992/09/14  00:00:00  neeri
  36. Maybe it works, maybe it doesn't
  37.  
  38. *********************************************************************/
  39.  
  40. #include "GUSIINET_P.h"
  41.  
  42. #include "TFileSpec.h"
  43. #include "Folders.h"
  44. #include "PLStringFuncs.h"
  45.  
  46. #ifdef __MWERKS__
  47. //
  48. // I disapprove of the way dnr.c is written
  49. // This disapproval gets stronger with every version
  50. //
  51. #include "dnr.c"
  52. #pragma require_prototypes reset
  53. #pragma cplusplus reset
  54. #endif
  55.  
  56. #if GENERATING68K
  57. #pragma segment GUSIINET
  58. #endif
  59.  
  60. pascal void DNRDone(struct hostInfo *, Boolean * done)
  61. {
  62.     *done = true;
  63. }
  64.  
  65. #if GENERATINGCFM
  66. RoutineDescriptor    uDNRDone = 
  67.         BUILD_ROUTINE_DESCRIPTOR(uppResultProcInfo, DNRDone);
  68. #else
  69. #define uDNRDone DNRDone
  70. #endif
  71.  
  72. int h_errno;
  73.  
  74. /*
  75.  *   Gethostbyname and gethostbyaddr each return a pointer to an
  76.  *   object with the following structure describing an Internet
  77.  *   host referenced by name or by address, respectively. This
  78.  *   structure contains the information obtained from the MacTCP
  79.  *   name server.
  80.  *
  81.  *   struct    hostent
  82.  *   {
  83.  *        char *h_name;
  84.  *        char **h_aliases;
  85.  *        int  h_addrtype;
  86.  *        int  h_length;
  87.  *        char **h_addr_list;
  88.  *   };
  89.  *   #define   h_addr  h_addr_list[0]
  90.  *
  91.  *   The members of this structure are:
  92.  *
  93.  *   h_name       Official name of the host.
  94.  *
  95.  *   h_aliases    A zero terminated array of alternate names for the host.
  96.  *
  97.  *   h_addrtype   The type of address being  returned; always AF_INET.
  98.  *
  99.  *   h_length     The length, in bytes, of the address.
  100.  *
  101.  *   h_addr_list  A zero terminated array of network addresses for the host.
  102.  *
  103.  *   Error return status from gethostbyname and gethostbyaddr  is
  104.  *   indicated by return of a null pointer.  The external integer
  105.  *   h_errno may then  be checked  to  see  whether  this  is  a
  106.  *   temporary  failure  or  an  invalid  or  unknown  host.  The
  107.  *   routine herror  can  be  used  to  print  an error  message
  108.  *   describing the failure.  If its argument string is non-NULL,
  109.  *   it is printed, followed by a colon and a space.   The  error
  110.  *   message is printed with a trailing newline.
  111.  *
  112.  *   h_errno can have the following values:
  113.  *
  114.  *     HOST_NOT_FOUND  No such host is known.
  115.  *
  116.  *     TRY_AGAIN    This is usually a temporary error and
  117.  *                    means   that  the  local  server  did  not
  118.  *                    receive a response from  an  authoritative
  119.  *                    server.   A  retry at some later time may
  120.  *                    succeed.
  121.  *
  122.  *     NO_RECOVERY    Some unexpected server failure was encountered.
  123.  *                     This is a non-recoverable error.
  124.  *
  125.  *     NO_DATA        The requested name is valid but  does  not
  126.  *                    have   an IP  address;  this  is not  a
  127.  *                    temporary error. This means that the  name
  128.  *                    is known  to the name server but there is
  129.  *                    no address  associated  with  this  name.
  130.  *                    Another type of request to the name server
  131.  *                    using this domain name will result in  an
  132.  *                    answer;  for example, a mail-forwarder may
  133.  *                    be registered for this domain.
  134.  *                    (NOT GENERATED BY THIS IMPLEMENTATION)
  135.  */
  136.  
  137. static struct hostInfo macHost;
  138.  
  139. #define MAXALIASES 0
  140. static char *aliasPtrs[MAXALIASES+1] = {NULL};
  141. static ip_addr *addrPtrs[NUM_ALT_ADDRS+1];
  142.  
  143. static struct hostent  unixHost =
  144. {
  145.     macHost.cname,
  146.     aliasPtrs,
  147.     AF_INET,
  148.     sizeof(ip_addr),
  149.     (char **) addrPtrs
  150. };
  151.  
  152. inline struct in_addr make_in_addr(ip_addr addr)
  153. {
  154.     struct in_addr    res;
  155.  
  156.     res.s_addr    =    addr;
  157.  
  158.     return res;
  159. }
  160.  
  161. struct hostent * gethostbyname(char *name)
  162. {
  163.     Boolean done;
  164.     int i;
  165.  
  166.     if (INETSockets.Resolver()) {
  167.         h_errno = NO_RECOVERY;    
  168.         return NULL;
  169.     }
  170.     
  171.     for (i=0; i<NUM_ALT_ADDRS; i++)
  172.         macHost.addr[i] = 0;
  173.  
  174.     done = false;
  175.  
  176.     if (StrToAddr(name, &macHost, ResultUPP(&uDNRDone), (char *) &done) == cacheFault)
  177.         SPINP(!done,SP_NAME,0L);
  178.  
  179.     switch (macHost.rtnCode) {
  180.     case noErr: break;
  181.  
  182.     case nameSyntaxErr:    h_errno = HOST_NOT_FOUND;    return(NULL);
  183.     case cacheFault:        h_errno = NO_RECOVERY;        return(NULL);
  184.     case noResultProc:    h_errno = NO_RECOVERY;        return(NULL);
  185.     case noNameServer:    h_errno = HOST_NOT_FOUND;    return(NULL);
  186.     case authNameErr:        h_errno = HOST_NOT_FOUND;    return(NULL);
  187.     case noAnsErr:            h_errno = TRY_AGAIN;            return(NULL);
  188.     case dnrErr:            h_errno = NO_RECOVERY;        return(NULL);
  189.     case outOfMemory:        h_errno = TRY_AGAIN;            return(NULL);
  190.     default:                    h_errno = NO_RECOVERY;        return(NULL);
  191.     }
  192.  
  193.     /* was the 'name' an IP address? */
  194.     if (macHost.cname[0] == 0) {
  195.         h_errno = HOST_NOT_FOUND;
  196.         return(NULL);
  197.     }
  198.  
  199.     /* for some reason there is a dot at the end of the name */
  200.     i = int(strlen(macHost.cname)) - 1;
  201.     if (macHost.cname[i] == '.')
  202.         macHost.cname[i] = 0;
  203.  
  204.     for (i=0; i<NUM_ALT_ADDRS && macHost.addr[i]!=0; i++)
  205.         addrPtrs[i] =    (ip_addr *) &macHost.addr[i];
  206.  
  207.     addrPtrs[i] = NULL;
  208.  
  209.     return &unixHost;
  210. }
  211.  
  212. struct hostent * gethostbyaddr(const char *addrP, int, int)
  213. {
  214.     Boolean    done;
  215.     int         i;
  216.  
  217.     if (INETSockets.Resolver()) {
  218.         h_errno = NO_RECOVERY;    
  219.         return NULL;
  220.     }
  221.  
  222.     for (i=0; i<NUM_ALT_ADDRS; i++)
  223.         macHost.addr[i] = 0;
  224.  
  225.     done = false;
  226.  
  227.     if (AddrToName(*(ip_addr *)addrP, &macHost, ResultUPP(&uDNRDone), (char *) &done) == cacheFault)
  228.         SPINP(!done,SP_ADDR,0L);
  229.  
  230.     switch (macHost.rtnCode) {
  231.     case noErr:             break;
  232.  
  233.     case cacheFault:        h_errno = NO_RECOVERY;        return(NULL);
  234.     case noNameServer:    h_errno = HOST_NOT_FOUND;    return(NULL);
  235.     case authNameErr:        h_errno = HOST_NOT_FOUND;    return(NULL);
  236.     case noAnsErr:            h_errno = TRY_AGAIN;            return(NULL);
  237.     case dnrErr:            h_errno = NO_RECOVERY;        return(NULL);
  238.     case outOfMemory:        h_errno = TRY_AGAIN;            return(NULL);
  239.     default:                    h_errno = NO_RECOVERY;        return(NULL);
  240.     }
  241.  
  242.     /* for some reason there is a dot at the end of the name */
  243.     i = int(strlen(macHost.cname)) - 1;
  244.     if (macHost.cname[i] == '.')
  245.         macHost.cname[i] = 0;
  246.  
  247.     for (i=0; i<NUM_ALT_ADDRS; i++)
  248.         addrPtrs[i] = (ip_addr *) &macHost.addr[i];
  249.  
  250.     addrPtrs[NUM_ALT_ADDRS] = NULL;
  251.  
  252.     return &unixHost;
  253. }
  254.  
  255. char * inet_ntoa(struct in_addr inaddr)
  256. {
  257.     if (INETSockets.Resolver()) {
  258.         h_errno = NO_RECOVERY;    
  259.         return NULL;
  260.     }
  261.     
  262.     (void) AddrToStr(inaddr.s_addr, macHost.cname);
  263.  
  264.     return macHost.cname;
  265. }
  266.  
  267. struct in_addr inet_addr(char *address)
  268. {
  269.     if (INETSockets.Resolver()) {
  270.         h_errno = NO_RECOVERY;    
  271.         return make_in_addr(0xFFFFFFFF);
  272.     }
  273.     
  274.     if (StrToAddr(address,&macHost,NULL,NULL) != noErr)
  275.         return make_in_addr(0xFFFFFFFF);
  276.  
  277.     /* was the 'address' really a name? */
  278.     if (macHost.cname[0] != 0)
  279.         return make_in_addr(0xFFFFFFFF);
  280.  
  281.     return make_in_addr(macHost.addr[0]);
  282. }
  283.  
  284. /*
  285.  * gethostname()
  286.  *
  287.  * Try to get my host name from DNR. If it fails, just return my
  288.  * IP address as ASCII. This is non-standard, but it's a mac,
  289.  * what do you want me to do?
  290.  */
  291.  
  292. int gethostname(char *machname, int buflen)
  293. {
  294.     in_addr ipaddr;
  295.     struct    hostent *hp;
  296.     struct GetAddrParamBlock pbr;
  297.  
  298.     pbr.ioCRefNum     = INETSockets.Driver();
  299.     pbr.csCode         = ipctlGetAddr;
  300.  
  301.     if (PBControlSync(ParmBlkPtr(&pbr)))
  302.         goto resign;
  303.  
  304.     ipaddr    =    make_in_addr(pbr.ourAddress);
  305.  
  306.     hp = gethostbyaddr((char *) &ipaddr, sizeof(in_addr), AF_INET);
  307.  
  308.     if (!hp)
  309.         goto resign;
  310.     else
  311.         strncpy(machname, hp->h_name, unsigned(buflen));
  312.  
  313.     machname[buflen-1] = 0;  /* extra safeguard */
  314.  
  315.     return 0;
  316.  
  317. resign:
  318.     sprintf(machname, "%d.%d.%d.%d",
  319.                             ipaddr.s_addr>>24,
  320.                             ipaddr.s_addr>>16 & 0xff,
  321.                             ipaddr.s_addr>>8 & 0xff,
  322.                             ipaddr.s_addr & 0xff);
  323.     return 0;
  324. }
  325.  
  326.  
  327. /*
  328.  *    getservbybname()
  329.  *
  330.  */
  331.  
  332. static char * servlist[] =
  333. {
  334.     "echo             7/udp",
  335.     "discard         9/udp",
  336.     "time            37/udp",
  337.     "domain        53/udp",
  338.     "sunrpc       111/udp",
  339.     "tftp           69/udp",
  340.     "biff           512/udp",
  341.     "who           513/udp",
  342.     "talk           517/udp",
  343.     "ftp-data       20/tcp",
  344.     "ftp           21/tcp",
  345.     "telnet       23/tcp",
  346.     "smtp           25/tcp",
  347.     "time           37/tcp",
  348.     "whois           43/tcp",
  349.     "domain           53/tcp",
  350.     "hostnames  101/tcp",
  351.     "nntp           119/tcp",
  352.     "finger       79/tcp",
  353.     "ntp           123/tcp",
  354.     "uucp           540/tcp",
  355.     NULL
  356. };
  357.  
  358. static char                 servline[128];
  359. static struct servent    serv;
  360. static FILE *                 servfil;
  361. static int                    servptr;
  362. static char *                servalias[8];
  363. static int                    servstay = 0;
  364.  
  365. void setservent(int stayopen)
  366. {
  367.     if (servfil && servfil != (FILE *) -1) {
  368.         rewind(servfil);
  369.     }
  370.     servptr    = 0;
  371.     servstay = servstay || stayopen;
  372. }
  373.  
  374. void endservent()
  375. {
  376.     if (servfil && servfil != (FILE *) -1) {
  377.         fclose(servfil);
  378.         servfil = NULL;
  379.     }
  380.     
  381.     servstay = 0;
  382. }
  383.  
  384. struct servent *  getservent()
  385. {
  386.     char *    p;
  387.     int        aliascount;
  388.     
  389.     if (!servfil) {
  390.         TFileSpec serv;
  391.         
  392.         if (!FindFolder(
  393.                 kOnSystemDisk, 
  394.                 kPreferencesFolderType, 
  395.                 kDontCreateFolder, 
  396.                 &serv.vRefNum,
  397.                 &serv.parID)
  398.         ) {
  399.             PLstrcpy(serv.name, (StringPtr) "\p/etc/services");
  400.         
  401.             if (servfil = fopen(serv.FullPath(), "r"))
  402.                 goto retry;
  403.         }    
  404.         servfil     = (FILE *) -1;
  405.         servptr    = 0;
  406.     }
  407.     
  408. retry:
  409.     if (servfil == (FILE *) -1)
  410.         if (!servlist[servptr])
  411.             return (struct servent *) NULL;
  412.         else
  413.             strcpy(servline, servlist[servptr++]);
  414.     else if (!(fgets(servline, 128, servfil)))
  415.         return (struct servent *) NULL;
  416.         
  417.     if (p = strpbrk(servline, "#\n"))
  418.         *p = 0;
  419.     if (!servline[0])
  420.         goto retry;
  421.     
  422.     if (!(serv.s_name = strtok(servline, " \t")))
  423.         goto retry;
  424.         
  425.     if (!(p = strtok(NULL, " \t")))
  426.         goto retry;
  427.     
  428.     if (!(serv.s_proto = strpbrk(p, "/,")))
  429.         goto retry;
  430.         
  431.     *serv.s_proto++     = 0;
  432.     serv.s_port         = htons(atoi(p));
  433.     serv.s_aliases     = servalias;
  434.     
  435.     for (aliascount = 0; aliascount < 7; ) 
  436.         if (!(servalias[aliascount++] = strtok(NULL, " \t")))
  437.             break;
  438.     
  439.     servalias[aliascount] = NULL;
  440.     
  441.     return &serv;
  442. }
  443.  
  444. struct servent * getservbyname(const char * name, const char * proto)
  445. {
  446.     struct servent *     ent;
  447.     char **                 al;
  448.     setservent(0);
  449.     
  450.     while (ent = getservent()) {
  451.         if (!strcmp(name, ent->s_name))
  452.             goto haveName;
  453.         
  454.         for (al = ent->s_aliases; *al; ++al)
  455.             if (!strcmp(name, *al))
  456.                 goto haveName;
  457.         
  458.         continue;
  459. haveName:
  460.         if (!proto || !strcmp(proto, ent->s_proto))
  461.             break;
  462.     }
  463.     
  464.     if (!servstay)
  465.         endservent();
  466.     
  467.     return ent;
  468. }
  469.  
  470. struct servent * getservbyport(int port, const char * proto)
  471. {
  472.     struct servent * ent;
  473.     
  474.     setservent(0);
  475.     
  476.     while (ent = getservent())
  477.         if (port == ent->s_port && (!proto || !strcmp(proto, ent->s_proto)))
  478.             break;
  479.     
  480.     if (!servstay)
  481.         endservent();
  482.     
  483.     return ent;
  484. }
  485.  
  486. static    char    tcp[] = "tcp";
  487. static    char    udp[] = "udp";
  488. #define    MAX_PROTOENT            10
  489. static     struct protoent        protoents[MAX_PROTOENT];
  490. static     int                        protoent_count=0;
  491.  
  492. struct protoent * getprotobyname(const char * name)
  493. {
  494.     struct protoent *pe;
  495.  
  496.     pe = &protoents[protoent_count];
  497.     if (strcmp(name, "udp") == 0) {
  498.         pe->p_name = udp;
  499.         pe->p_proto = IPPROTO_UDP;
  500.     } else if (strcmp (name, "tcp") == 0)  {
  501.         pe->p_name = tcp;
  502.         pe->p_proto = IPPROTO_TCP;
  503.     } else {
  504.         errno = EPROTONOSUPPORT;
  505.         return NULL;
  506.     }
  507.     pe->p_aliases = aliasPtrs;
  508.     protoent_count = (protoent_count +1) % MAX_PROTOENT;
  509.     return pe;
  510. }
  511.